#pragma once
//============================================================================
// Copyright (C) 2003-2013 Brett R. Jones
//
// Issued to public domain 2013
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================

#include <VxUtilLib/VxMutex.h>
#include <string>

class DbBase;
struct sqlite3;
struct sqlite3_stmt;

class DbCursor
{
public:
	//=== vars ===//
	DbBase *		m_poDbBase;
	sqlite3_stmt *  m_poStmt;

	//=== constructor ===//
	DbCursor();

	//! close database and delete ourself
	void			close( void );

	//! fetch next row from table
	bool			getNextRow( void );
	//! return 8 bit integer from column
	U8				getByte( int iColumnIdx );
	//! return 32 bit integer from column
	S32				getS32( int iColumnIdx );
	//! return 64 bit integer from column
	S64				getS64( int iColumnIdx );
	//! return float from column
	F32				getF32( int iColumnIdx );
	//! return float from column
	F64				getF64( int iColumnIdx );
	//! return string from column
	const char *	getString(int iColumnIdx );
	//! return blob from column.. 
	//! if( piMaxLen != null ) then return length of blob in piMaxLen 
	void *			getBlob( int iColumnIdx, int * piMaxLen = NULL );
};

class DbBase
{
public:
	//=== vars ===//
	std::string			m_strDbFileName;
    BOOL				m_bDbInitialized;		// if true database initialized
    int					m_iDbVersion;
    sqlite3 *			m_poDb;
	VxMutex				m_oDbMutex;

	//=== constructor ===//
	DbBase();
	//=== destructor ===//
	~DbBase();

	//=== helpers ===//
	RCODE				SqlExec( std::string strCmd )			{ return SqlExec( (char *)strCmd.c_str() ); }
	RCODE				RunQuery( std::string strCmd )			{ return RunQuery( (char *)strCmd.c_str() ); }
	DbCursor *			StartQuery( std::string strCmd )		{ return StartQuery( (char *)strCmd.c_str() ); }

	//=== overrides ===//
	//! create initial database.. 
	virtual RCODE		onCreateDatabase( int iDbVersion );
	//! upgrade db from old version to new version
	virtual RCODE		onUpgradeDatabase(int iOldDbVersion, int iNewDbVersion); 
	//! create tables in database 
	virtual RCODE		onCreateTables( int iDbVersion ) = 0;
	//! delete tables from database 
	virtual RCODE		onDeleteTables( int oldDbVersion ) = 0;

	//=== methods ===//
	//! Initialize the database.. if doesn't exist then call onCreateDatabase and onCreateTables
	//! if version does not match then call onDeleteTables and onCreateTables
	virtual RCODE		DbStartup( int iDbVersion, const char * pDbFileName );
	//! if version does not match then call onDeleteTables and onCreateTables
	virtual RCODE		DbStartup( int iDbVersion, std::string& strDbFileName ) { return DbStartup( iDbVersion, strDbFileName.c_str() ); }

	//! shutdown the database
	virtual RCODE		DbShutdown( void );

	//! open the database
	virtual RCODE		DbOpen( void );
	//! close the database
	virtual RCODE		DbClose( void );

	//! read database version from version table 
	virtual int			readDatabaseVersion( void );
	//! write database version to version table 
	virtual RCODE		writeDatabaseVersion( int iDbVersion );

 
	//! archive database into given directory
	virtual RCODE		DbArchive( const char * pArchiveDirectory, BOOL bClearExistingDb = false );

	//! open db then execute Sql statement then close db
	virtual RCODE		SqlExec( char * pSqlStatment );
	//! open db then execute Sql statement then close db
	virtual RCODE		SqlExec( const char * pSqlString, ... );

	//! start query and use DbCursor to access column's data.. be sure to call DbCursor.close() when done
	//! returns null if error
	virtual DbCursor *	StartQuery( char * pSqlString );
	//! open db then execute Sql statement then close db
	virtual DbCursor *	StartQuery( const char * pSqlString, ... );



	//! get the row id of the last inserted row
	virtual S64			GetLastInsertId( void );

	//! return true if table exists
	bool				DbTableExists( const char * pTableName );


};


